﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Text;
using Security2;

namespace UserRights
{
    public class UserRightsBaseCmdlet : PSCmdlet
    {
        protected bool IsUserAdmin()
        {
            var wi = System.Security.Principal.WindowsIdentity.GetCurrent();
            return new System.Security.Principal.WindowsPrincipal(wi)
                .IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
        }

        protected override void BeginProcessing()
        {
            //if (!IsUserAdmin())
            //{
            //    this.WriteError(new ErrorRecord(new UnauthorizedAccessException(), "AdministratorRoleRequired", ErrorCategory.PermissionDenied, Environment.UserName));
            //    this.StopProcessing();
            //}
        }
    }

    #region GetUserRight
    [Cmdlet("Get", "UserRight")]
    public class GetUserRight : UserRightsBaseCmdlet
    {
        private IdentityReference2[] accounts;
        private Lsa.Privileges? privileges;
        private string computerName;

        #region Parameters
        [Parameter(Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
        [ValidateNotNullOrEmpty()]
        public IdentityReference2[] Account
        {
            get { return accounts; }
            set { accounts = value; }
        }

        [Parameter(Position = 2, ValueFromPipelineByPropertyName = true)]
        public Lsa.Privileges? Privileges
        {
            get { return privileges; }
            set { privileges = value; }
        }

        [Parameter(ValueFromPipelineByPropertyName = true)]
        [ValidateNotNullOrEmpty()]
        public string ComputerName
        {
            get { return computerName; }
            set { computerName = value; }
        }

        #endregion

        protected override void BeginProcessing()
        {
            base.BeginProcessing();

            if (string.IsNullOrEmpty(computerName))
            {
                computerName = Environment.MachineName;
            }
        }
        protected override void ProcessRecord()
        {
            //if accounts and prvileges are not specified all rights are returned
            if (accounts == null && !privileges.HasValue)
            {
                try
                {
                    Lsa.UserRights.GetAllRights(computerName)
                        .ForEach(ur => this.WriteObject(ur));
                }
                catch (Exception ex)
                {
                    this.WriteError(new ErrorRecord(ex, "RightsEnumError", ErrorCategory.NotSpecified, computerName));
                }
                return;
            }

            //if the account is specified but not the privilege all rights associated with that account are returned
            if (accounts != null && !privileges.HasValue)
            {
                foreach (var account in accounts)
                {
                    try
                    {
                        Lsa.UserRights.GetRightsForAccount(computerName, account)
                            .ForEach(ur => this.WriteObject(ur));
                    }
                    catch (Exception ex)
                    {
                        this.WriteError(new ErrorRecord(ex, "RightsEnumError", ErrorCategory.NotSpecified, account));
                        continue;
                    }
                }
            }

            //if privilige is specified but not an acount all accounts are returned associated with that privilege
            if (accounts == null && privileges.HasValue)
            {
                try
                {
                    this.WriteObject(Lsa.UserRights.GetAccountsWithSpecificRight(computerName, privileges.Value));

                }
                catch (Exception ex)
                {
                    this.WriteError(new ErrorRecord(ex, "RightsEnumError", ErrorCategory.NotSpecified, privileges));
                }

                return;
            }
        }
    }
    #endregion

    #region GrantUserRight
    [Cmdlet("Grant", "UserRight")]
    public class GrantUserRight : UserRightsBaseCmdlet
    {
        private IdentityReference2[] accounts;
        private Lsa.Privileges privileges;
        private string computerName;
        SwitchParameter passThru;

        #region Parameters
        [Parameter(Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Mandatory = true)]
        [ValidateNotNullOrEmpty()]
        public IdentityReference2[] Account
        {
            get { return accounts; }
            set { accounts = value; }
        }

        [Parameter(Position = 2, ValueFromPipelineByPropertyName = true, Mandatory = true)]
        public Lsa.Privileges Privileges
        {
            get { return privileges; }
            set { privileges = value; }
        }

        [Parameter(ValueFromPipelineByPropertyName = true)]
        [ValidateNotNullOrEmpty()]
        public string ComputerName
        {
            get { return computerName; }
            set { computerName = value; }
        }

        [Parameter]
        public SwitchParameter PassThru
        {
            get { return passThru; }
            set { passThru = value; }
        }
        #endregion

        protected override void BeginProcessing()
        {
            base.BeginProcessing();

            if (string.IsNullOrEmpty(computerName))
            {
                computerName = Environment.MachineName;
            }
        }
        protected override void ProcessRecord()
        {
            foreach (var account in accounts)
            {
                try
                {
                    if (Lsa.UserRights.GetRightsForAccount(account).Where(ur => ur.Name == privileges).Count() > 0)
                    {
                        this.WriteWarning(string.Format("The account '{0}' does already have the right '{1}'", account, privileges));
                        continue;
                    }

                    Lsa.UserRights.GrantRight(computerName, account, privileges);

                    if (passThru)
                    {
                        this.WriteObject(Lsa.UserRights.GetAccountsWithSpecificRight(computerName, privileges));
                    }
                }
                catch (Exception ex)
                {
                    this.WriteError(new ErrorRecord(ex, "GrantRightError", ErrorCategory.NotSpecified, account));
                    continue;
                }
            }

        }
    }
#endregion

    #region RevokeUserRight
    [Cmdlet("Revoke", "UserRight")]
    public class RevokeUserRight : UserRightsBaseCmdlet
    {
        private IdentityReference2[] accounts;
        private Lsa.Privileges privileges;
        private string computerName;
        SwitchParameter passThru;

        #region Parameters
        [Parameter(Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Mandatory = true)]
        [ValidateNotNullOrEmpty()]
        public IdentityReference2[] Account
        {
            get { return accounts; }
            set { accounts = value; }
        }

        [Parameter(Position = 2, ValueFromPipelineByPropertyName = true, Mandatory = true)]
        public Lsa.Privileges Privileges
        {
            get { return privileges; }
            set { privileges = value; }
        }

        [Parameter(ValueFromPipelineByPropertyName = true)]
        [ValidateNotNullOrEmpty()]
        public string ComputerName
        {
            get { return computerName; }
            set { computerName = value; }
        }

        [Parameter]
        public SwitchParameter PassThru
        {
            get { return passThru; }
            set { passThru = value; }
        }
        #endregion

        protected override void BeginProcessing()
        {
            base.BeginProcessing();

            if (string.IsNullOrEmpty(computerName))
            {
                computerName = Environment.MachineName;
            }
        }
        protected override void ProcessRecord()
        {
            foreach (var account in accounts)
            {
                try
                {
                    if (Lsa.UserRights.GetRightsForAccount(account).Where(ur => ur.Name == privileges).Count() == 0)
                    {
                        this.WriteWarning(string.Format("The account '{0}' does not have granted the right '{1}'", account, privileges));
                        continue;
                    }

                    Lsa.UserRights.RevokeRight(computerName, account, privileges);

                    if (passThru)
                    {
                        this.WriteObject(Lsa.UserRights.GetAccountsWithSpecificRight(computerName, privileges));
                    }
                }
                catch (Exception ex)
                {
                    this.WriteError(new ErrorRecord(ex, "RevokeRightError", ErrorCategory.NotSpecified, account));
                    continue;
                }
            }

        }
    }
    #endregion
}